param ([switch]$SendEmail = $false, [string]$OneOffEmailAddr = "default")
# By default do not send email.

#requires -version 1
Set-PSDebug -Strict

##Requires -pssnapin Microsoft.Exchange.Management.PowerShell.Admin
$exchangeSnapinFound = $False 
Get-PSSnapin | 
	ForEach { 
		If ($_.Name -EQ 'Microsoft.Exchange.Management.PowerShell.Admin') { 
			$exchangeSnapinFound = $True
		} 
	}
If (-Not $exchangeSnapinFound) { 
	Add-PSSnapin 'Microsoft.Exchange.Management.PowerShell.Admin' -ErrorAction 'Stop'
} 


#---------------8<---------------Function Time-Zone
Function Get-TimeZoneName {
	$timeZone = get-WmiObject -Query 'Select * From Win32_TimeZone'
	if ($timeZone.DaylightInEffect) {
		$timeZone.DaylightName
	}else{
		$timeZone.StandardName
	}
} #end of Function Get-TimeZoneName

#---------------8<---------------Function WhiteSpace
Function Get-WhiteSpace([string]$server, [string]$MailboxDatabaseName, [array]$WSEvents) {
	$Array = @()
	$Result = @()
	$WSpace = $WSEvents | Where-Object {$_.Message.Contains($MailboxDatabaseName)}
	#$Check = $WSpace -is [array]
	If ($WSpace -is [array]) {
		Write-Host 'WSpace is Array?: ' ($WSpace -is [array])
		ForEach ($item in $WSpace) {
			$Array = $item.message.split("`"")
			$EndString = $Array[2].indexof("megabytes ")-6
			#write-host $mbnamearray[1]
			[int]$Result = $Array[2].Substring(5,$EndString)
		}
	} else {
		Write-Host 'WSpace is Array?: ' ($WSpace -is [array])
		If ($WSpace -ne $null) {
			$Array = $WSpace.message.split("`"")
			$EndString = $Array[2].indexof("megabytes ")-6
			#write-host $mbnamearray[1]
			[int]$Result = $Array[2].Substring(5,$EndString)
		} else {
			$Result = "No defrag last day"
		}
	}
	$Result
} #end of Function Get-Whitespace

#---------------8<---------------Variables
$ServerName = $Env:COMPUTERNAME
$FromServer = "&nbsp;<span class=""style5"">" + $ServerName + "</span>"
$now = get-date
$date = get-date -format d #get-date -uformat "%m-%d-%Y"
$TZ = Get-TimeZoneName
$ServerSkipList = "C:\WINDOWS\Scripts\ExServersToSkip.csv"
$Logo = "<span class=""style14"">perot</span><span class=""style10"">systems</span><span class=""style11"">&#0174;</span>&nbsp;"
#---------------8<---------------Company Info and Mail
$ReportType = "Exchange"
$Company = "CHW"
$Subject = $Company + " " + $ReportType + " Report - " + $date
$Header = $Company + " " + $ReportType + " Report - Report as on " + $now + " " + $TZ + $FromServer + "<br>" + "`r`n"
$SMTPHost = "162.135.4.20"
$From = """Exchange Operations"" <ExchangeOp@ps.net>"
if ($oneOffEmailAddr.tolower() -eq "default") {
	$To = "<DL-GIS-MessagingHealthcare1@ps.net>"
	$Cc = "<bill.branson@chw.edu>"
	$Bcc = "<ExchangeOp@ps.net>"
} else {
	$To = $oneOffEmailAddr
	$Cc = ""
	$BCc = ""
}
$attach = ""
#---------------8<---------------Variables
$filelocation = $Company + $ReportType + "Report.html"
$Code = @()
$Write = @()

#---------------8<---------------HEAD HTML Code
function Head() {
#$Write = ""
$Write += "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01//EN""  ""http://www.w3.org/TR/html4/strict.dtd"">" + "`r`n"
$Write += "<html>" + "`r`n"
$Write += "<head>" + "`r`n"
$Write += "<meta http-equiv=""Content-Type"" content=""text/html; charset=iso-8859-1"">" + "`r`n"
$title = "<title>" + $Subject + "</title>" + "`r`n"
$Write += $title
$Head = @'
<style>
BODY{font-family:tahoma;} 
TABLE{border-width: 1px;cellspacing: 0;cellpadding: 3;}
TH{border-width: 1px;font-size: 11px;text-align: center;background-color: #999999;font-weight: bold;}
TD{border-width: 1px;font-size: 9px;text-align: center;border-width: 1px;border-style: solid;}
.style5{color: #FFFFFF;}
.style9{background-color: #000000;}
.style10{font-family: Verdana;font-size: 14px;font-weight: bold;}
.style11{font-size: 9px;vertical-align: text-top;}
.style12{font-size: 9px;color: #C0C0C0;}
.style13{font-family: Tahoma;font-size: 9px;color: #FFFFFF;border: 1px solid #C0C0C0;}
.style14{color: #FE000B;font-family: Verdana;font-size: 14px;font-weight: bold;}
</style>
'@
$Write += $Head
$Write += "</head><body>" + "`r`n"
$Write += "<H6>" + "`r`n"
$Write += $Header
$Write += "<br>" + "`r`n"
$Write += "Backup: <span style=""background-color:yellow"">YELLOW</span> = &gt; 1 day &nbsp; <span style=""background-color:red"">RED</span> = &gt; 2 days <br>" + "`r`n"
$Write += "Whitespace: <span style=""background-color:yellow"">YELLOW</span> = &gt; 20% &nbsp; <span style=""background-color:red"">RED</span> = &gt; 30% <br>" + "`r`n"
$Write += "Free Space: <span style=""background-color:yellow"">YELLOW</span> = &gt; 15% &nbsp; <span style=""background-color:red"">RED</span> = &gt; 5% <br>" + "`r`n"
$Write += "</H6>" + "`r`n"
$Write += "<table>" + "`r`n"
Return $Write
} #end of Function Head

#---------------8<---------------HEADER HTML Code
function Header() {
#$Write = ""
$Write += "<tr>" + "`r`n"
$Write += "<th>Server\StorageGroup\Database</th>" + "`r`n"
$Write += "<th>Size (GB)</th>" + "`r`n"
$Write += "<th>Mailbox Count</th>" + "`r`n"
$Write += "<th>LastFullBackup</th>" + "`r`n"
$Write += "<th>WhiteSpace (MB)</th>" + "`r`n"
$Write += "<th>Capacity (GB)</th>" + "`r`n"
$Write += "<th>Free Space (GB)</th>" + "`r`n"
$Write += "<th>Free Space (%)</th>" + "`r`n"
$Write += "</tr>" + "`r`n"
Return $Write
} # end of Function Header

#---------------8<---------------BODY HTML Code
function Body($objItem,$MDBSize,$MBXCount,$BackupDays,$WhiteSpace,$DiskCapacity,$FreeOnStorage,$FreeOnStorageProc) {
	$Write += "<tr>" + "`r`n"
	$Write += "<td>$objItem</td>" + "`r`n"
	#write-host "Size (GB): " $MDBSize
	$Write += "<td>$MDBSize</td>" + "`r`n"
	Write-Host '$MBXCount: ' $MBXCount
	if ($MBXCount -ne $null)
		{$Write += "<td>$MBXCount</td>" + "`r`n"}
	else
		{$Write += "<td>-</td>" + "`r`n"}
	#write-host $CheckLastBackup
	#write-host $CheckLastBackup.days
	write-host '$BackupDays' $BackupDays
	if ($BackupDays -eq "-")
		{$Write += "<td>-</td>" + "`r`n"}
	elseif ($BackupDays -le -2)
		{$Write += "<td bgcolor=red>$LastBackup</td>" + "`r`n"}
	elseif ($BackupDays -eq -1)
		{$Write += "<td bgcolor=yellow>$LastBackup</td>" + "`r`n"}
	elseif ($BackupDays -eq 0)
		{$Write += "<td bgcolor=#BBFBA8>$LastBackup</td>" + "`r`n"}
	else
		{$Write += "<td bgcolor=#BBFBA8>$LastBackup</td>" + "`r`n"}
	# Write-Host '$WhiteSpace2: ' $WhiteSpace
	# Write-Host $WhiteSpace.GetType()
	
	if ($WhiteSpace -is [int] -and $WhiteSpace -ge $L30)
		{$Write += "<td bgcolor=red>$WhiteSpace</td>" + "`r`n"}
	elseif ($WhiteSpace -is [int] -and $WhiteSpace -ge $L20)
		{$Write += "<td bgcolor=yellow>$WhiteSpace</td>" + "`r`n"}
	elseif ($WhiteSpace -eq "No defrag last day")
		{$Write += "<td bgcolor=yellow>$WhiteSpace</td>" + "`r`n"}
	else
		{$Write += "<td>$WhiteSpace</td>" + "`r`n"}
	$Write += "<td>$DiskCapacity</td>" + "`r`n"
	$Write += "<td>$FreeOnStorage</td>" + "`r`n"
	#write-host '$FreeOnStorageProc2: ' $FreeOnStorageProc
	If ($FreeOnStorageProc -le 5)
		{$Write += "<td bgcolor=red>$FreeOnStorageProc</td>" + "`r`n"}
	ElseIf ($FreeOnStorageProc -le 15)
		{$Write += "<td bgcolor=yellow>$FreeOnStorageProc</td>" + "`r`n"}
	else
		{$Write += "<td bgcolor=#BBFBA8>$FreeOnStorageProc</td>" + "`r`n"}
	$Write += "</tr>" + "`r`n"
	Return $Write
} #end of Function body

#---------------8<---------------FOOTER HTML Code
Function Footer() {
$finish = Get-Date
$Write += "</table>" + "`r`n"
$Write += "<br>" + "`r`n"
$Write += "<table class=""style9"">" + "`r`n"
$Write += "<tr>" + "`r`n"
$Write += "<td style=""color #CCCCCC;"" class=""style13"">Finished processing " + $TotalServers + " servers @ " + $finish + " " + $TZ + "</td>" + "`r`n"
$Write += "</tr>" + "`r`n"
$Write += "</table>" + "`r`n"
$Write += "$Logo<span class=""style12"">Powered by Ajlan</span>" + "`r`n"
$Write += "</body></html>" + "`r`n"
Return $Write
} #end of Function Footer

#---------------8<---------------Function Email
Function sendmail($body) {
    $SmtpClient = new-object system.net.mail.smtpClient 
    $MailMessage = New-Object system.net.mail.mailmessage 
    $SmtpClient.Host = $SMTPHost #"<Your Email Server>"
    $MailMessage.From = $From
    $MailMessage.To.add($To)
	If ($Cc){
		$MailMessage.Cc.add($Cc)
	}
	If ($Bcc){
		$MailMessage.Bcc.add($Bcc)
	}
    $MailMessage.Subject = $Subject
    $MailMessage.IsBodyHtml = $True
    $MailMessage.Body = $body #Get-Content .\report.html 	
	If ($attach){
		$Attachment = new-object System.Net.Mail.Attachment($attach)
		$MailMessage.Attachements.Add($Attachment)
	}
   $SmtpClient.Send($mailmessage) 
} #end of Function sendmail


$Code += Head
#Write-Host '$Code1: ' $Code
#$Code += Header
#Write-Host '$Code2: ' $Code

#---------------8<---------------
# Build list of Exchange Servers
#---------------8<---------------Function Main

## Adding the following to skip the numerous servers that are not really in the environment
## but clutter the output.  Reads ExServersToSkip.csv into an array and excludes servers
## matching those names from the lists. -dfr 03/24/2010
$skiplist = @()
Import-Csv $ServerSkipList | ForEach-Object {$skiplist += $_.Servername}

#These are Ajlan's original lines
#$exchange2007servers = @(Get-MailboxServer | sort) #Get-ExchangeServer |where-object {$_.admindisplayversion.major -eq 8 -and $_.IsMailboxServer -eq $true }
#$exchange2003servers = @(Get-ExchangeServer | where-object {$_.admindisplayversion.major -ne 8 } | sort)

#These are mine with the skiplist test added -dfr
$exchange2007servers = @(Get-MailboxServer | Where-Object {$skiplist -notcontains $_.name} | sort) 
$exchange2003servers = @(Get-ExchangeServer | Where-Object {$skiplist -notcontains $_.name -and $_.admindisplayversion.major -ne 8 } | sort)

#---------------8<---------------Function Main Exchange 2007
foreach ($server in $exchange2007servers) {
	Write-Host "======================"
	$server.name
	Write-Host "Getting Mailbox Databases"
	$ServerDatabases = Get-MailboxDatabase -Status -server $server | sort
		If ($ServerDatabases -ne $null) {
			$Code += Header
			$Volumes = Get-WMIObject Win32_Volume -computerName $server #pulled this here so it only runs once per server
			#$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-1)) #A lower limit on how far back to look in the eventlog
			#Write-Host '$WmidtQueryDT: ' $WmidtQueryDT
			#get all 1221 events from the server back to $WmidtQueryDT (1 day).  Brought this out of Get-Whitespace Function so it will only run once per server (very slow)
			Write-Host "Getting 1221 events"
			#$WhiteSpaceEvents = Get-WmiObject -computer $server -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'")
			$WhiteSpaceEvents = Get-EventLog -ComputerName $server.name -log Application -Source "MsExchangeIS Mailbox Store" -EntryType Information -after (get-date).addHours(-36) | ? {$_.EventID -eq 1221 } 

			foreach ($MailboxDatabase in $ServerDatabases) {
				Write-Host "*****************"
				$L20 = $null
				$L30 = $null
				$DiskCapacity = $null
				$FreeOnStorage = $null
				$FreeOnStorageProc = $null
				$MDBSize = $null
				$WhiteSpace =$null
				$MBXCount = $null
				$BackupDays = $null
				
				Write-Host "DatabaseName: " $MailboxDatabase.name
				$edbfilepath = $MailboxDatabase.edbfilepath.ToString()
				#$edbpath = $edbfilepath.ToUpper()
				#convert absolute path to UNC path
				$path = "`\`\" + $server + "`\" + $MailboxDatabase.EdbFilePath.DriveName.Remove(1).ToString() + "$"+ $MailboxDatabase.EdbFilePath.PathName.Remove(0,2)
				Write-Host '$path: ' $path
				$dbsize = Get-ChildItem $path
				#Write-Host '$dbsize: ' $dbsize
				$mailboxcount = Get-MailboxStatistics -database "$MailboxDatabase" | measure-object
				
				$start = $path.LastIndexOf('\')
				$dbName = $path.Substring($start +1).remove($path.Substring($start +1).length -4)
				#$mailboxpath = "$server\$MailboxDatabase.name"
				#Write-Host "DatabaseFile: " $mailboxpath
				$edbpathlength = 0
				#$volumes = Get-WMIObject Win32_Volume -computerName $server  #does not need to run more than once per server
				foreach ($volItem in $Volumes) {
					If ( $edbfilepath.ToUpper().startswith($volItem.name.ToUpper()) ) {
						write-host $volItem.name.ToUpper() "   -   " $edbfilepath.startswith($volItem.name) "   -   " $volItem.name.length			
						If ($edbpathlength -lt $volItem.name.length) {	
							$edbpathlength = $volItem.name.length
							$edbfilepathvolumename = $volItem.name
							$edbfilepathfreespace =  $volItem.freespace
							$edbfilepathcapacity = $volItem.capacity
						}
					}
				}
				
				$VolumeName = $edbfilepathvolumename
				$FreeOnStorage = "{0:N2}" -f ($edbfilepathfreespace/1GB)
				$DiskCapacity = "{0:N2}" -f ($edbfilepathcapacity/1GB)

				Write-Host '$VolumeName: ' $VolumeName
				Write-Host '$DiskCapacity: ' $DiskCapacity
				Write-Host '$FreeOnStorage: ' $FreeOnStorage
				$FreeOnStoragePercent = ([int] $FreeOnStorage / [int] $DiskCapacity)
				$FreeOnStoragePercent = [int] ($FreeOnStoragePercent * 100)
				Write-Host '$FreeOnStoragePercent2: ' $FreeOnStoragePercent
				$MDBSize = ("{0:N2}" -f ($dbsize.Length/1GB))
				Write-Host 'MDBSize: ' $MDBSize
				$MBXCount = $mailboxcount.count
				$LastBackup = $MailboxDatabase.LastFullBackup
				Write-Host '$LastBackup: ' $LastBackup
				$WhiteSpace = Get-WhiteSpace $server $MailboxDatabase.name $WhiteSpaceEvents
				Write-Host '$WhiteSpace: ' $WhiteSpace
				If ($LastBackup -ne $null) { 
					$CheckLastBackup = New-TimeSpan $(get-date) $($LastBackup)
					$BackupDays = $CheckLastBackup.days
				}	
				else { $BackupDays = "-"}
				$L20 = [int] $MDBSize * 1024 * .2
				$L30 = [int] $MDBSize * 1024 * .3
				Write-Host '$L20: ' $L20
				Write-Host '$L30: ' $L30
				
				$Code += (body $MailboxDatabase $MDBSize $MBXCount $BackupDays $WhiteSpace $DiskCapacity $FreeOnStorage $FreeOnStoragePercent)
			}
		}
}  # End of Main Exchange 2007 loop

#---------------8<---------------Function Main Exchange 2003
foreach ($server in $exchange2003servers) {
	Write-Host "======================"
	$server.name
	Write-Host "Getting Mailbox databases"
	$ServerDatabases = Get-MailboxDatabase -Status -server $server | sort
		If ($ServerDatabases -ne $null) {
			$Code += Header
			$volumes = Get-WMIObject Win32_Volume -computerName $server #pulled this here so it only runs once per server
			#$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-1)) #A lower limit on how far back to look in the eventlog
			#Write-Host '$WmidtQueryDT: ' $WmidtQueryDT
			#get all 1221 events from the server back to $WmidtQueryDT (1 day).  Brought this out of Get-Whitespace Function so it will only run once per server (very slow)
			Write-Host "Getting 1221 events"
			#$WhiteSpaceEvents = Get-WmiObject -computer $server -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'")
			$WhiteSpaceEvents = Get-EventLog -ComputerName $server.name -log Application -Source "MsExchangeIS Mailbox Store" -EntryType Information -after (get-date).addHours(-36) | ? {$_.EventID -eq 1221 } 

			foreach ($MailboxDatabase in $ServerDatabases) {
				Write-Host "*****************"
				$L20 = $null
				$L30 = $null
				$DiskCapacity = $null
				$FreeOnStorage = $null
				$FreeOnStorageProc = $null
				$MDBSize = $null
				$WhiteSpace = $null
				$MBXCount = $null
				$BackupDays = $null
				
				Write-Host "DatabaseName: " $MailboxDatabase.name
				$edb = $MailboxDatabase.name
				$edbfilepath = $MailboxDatabase.edbfilepath.ToString()
				#$edbpath = $edbfilepath.ToUpper()
				Write-Host '$edbpath: ' $edbfilepath.ToUpper()
				$path = "`\`\" + $server + "`\" + $MailboxDatabase.EdbFilePath.DriveName.Remove(1).ToString() + "$"+ $MailboxDatabase.EdbFilePath.PathName.Remove(0,2)
				Write-Host '$path: ' $path
				$dbsize = Get-ChildItem $path
				$mailboxcount = Get-MailboxDatabase -Server $server | where { $_.Name -eq $MailboxDatabase.name } | Get-Mailbox -ResultSize:Unlimited | measure-object
				$edbpathlength = 0
				#$volumes = Get-WMIObject Win32_Volume -computerName $server   #does not need to run more than once per server
				foreach ($volItem in $volumes) {
					If ( $edbfilepath.ToUpper().startswith($volItem.name.ToUpper()) ) {
						write-host $volItem.name.ToUpper() "   -   " $edbfilepath.startswith($volItem.name) "   -   " $volItem.name.length
						If ($edbpathlength -lt $volItem.name.length) {	
							$edbpathlength = $volItem.name.length
							$edbfilepathvolumename = $volItem.name
							$edbfilepathfreespace =  $volItem.freespace
							$edbfilepathcapacity = $volItem.capacity
						}
					}
				}
				
				$VolumeName = $edbfilepathvolumename
				$FreeOnStorage = "{0:N2}" -f ($edbfilepathfreespace/1GB)
				$DiskCapacity = "{0:N2}" -f ($edbfilepathcapacity/1GB)
				
				Write-Host '$VolumeName: ' $VolumeName
				Write-Host '$DiskCapacity: ' $DiskCapacity
				Write-Host '$FreeOnStorage: ' $FreeOnStorage
				$FreeOnStoragePercent = ([int] $FreeOnStorage / [int] $DiskCapacity)
				$FreeOnStoragePercent = [int] ($FreeOnStoragePercent * 100)
				Write-Host '$FreeOnStoragePercent2: ' $FreeOnStoragePercent
				$MDBSize = ("{0:N2}" -f ($dbsize.Length/1GB))
				Write-Host 'MDBSize: ' $MDBSize
				$MBXCount = $mailboxcount.count
				$LastBackup = $MailboxDatabase.LastFullBackup
				Write-Host '$LastBackup: ' $LastBackup
				$WhiteSpace = Get-WhiteSpace $server $MailboxDatabase.name $WhiteSpaceEvents
				Write-Host '$WhiteSpace: ' $WhiteSpace
				If ($LastBackup -ne $null)
				{ 
					$CheckLastBackup = New-TimeSpan $(get-date) $($LastBackup)
					$BackupDays = $CheckLastBackup.days
				}	
				else
					{ $BackupDays = "-"}
				$L20 = [int] $MDBSize * 1024 * .2
				$L30 = [int] $MDBSize * 1024 * .3
				Write-Host '$L20: ' $L20
				Write-Host '$L30: ' $L30
				$Code += (body $MailboxDatabase $MDBSize $MBXCount $BackupDays $WhiteSpace $DiskCapacity $FreeOnStorage $FreeOnStoragePercent)
			}
		}
}  # End of Main Exchange 2003 loop

$TotalServers = $exchange2007servers.Count + $exchange2003servers.Count

#---------------8<---------------Wrap Up
$Code += Footer
# Write-Host '$Code3: ' $Code
#Write-Host $Code

$Code | out-file $filelocation

$body = $Code


write-host "Done"

If ($SendEmail)   #switch parameter passed as parameter
	{Sendmail $body
	Write-Host "Email Sent!"}
else
	{Write-Host "No Email!"}

